﻿using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TicketDesk.Domain.Legacy
{
    public static class LegacyBackgroundMigrator
    {
        public static Task MigrationTask { get; private set; }

        public static CancellationTokenSource Canceler;

        private static LegacyMigrator Migrator { get; set; }

        public static void BeginMigration(LegacyMigrator migrator)
        {
            if (
                MigrationTask == null || 
                (
                    MigrationTask.Status != TaskStatus.Running || 
                    MigrationTask.Status != TaskStatus.Created ||
                    MigrationTask.Status != TaskStatus.WaitingForActivation ||
                    MigrationTask.Status != TaskStatus.WaitingForChildrenToComplete ||
                    MigrationTask.Status != TaskStatus.WaitingToRun
                ))
            {
                Canceler = new CancellationTokenSource();
                var token = Canceler.Token;
                Reset();
                Migrator = migrator;
                Migrator.Canceler = Canceler;
                try
                {
                    MigrationTask = Task.Factory.StartNew(() =>
                    {
                        Migrator.StatusChanged += Migrator_StatusChanged;
                        Migrator.Migrate();
                        token.ThrowIfCancellationRequested();
                    }, token);
                    
                }
                catch (OperationCanceledException)
                {
                    //we'll eat the exceptions if thrown due to cancellation
                }
            }
        }

        /// <summary>
        /// Cancels any operation currently in progress
        /// </summary>
        public static void CancelMigration()
        {
            if (Canceler != null)
            {
                Canceler.Cancel();
            }
        }

        /// <summary>
        /// Resets the Background mgrator to make it ready for a new migration
        /// </summary>
        public static void Reset()
        {
            if (MessageStack != null)
            {
                MessageStack = null;
            }
            if (MigrationTask != null)
            {
                MigrationTask.Dispose();
                MigrationTask = null;
            }
        }

        private static void Migrator_StatusChanged(string[] messages)
        {
            foreach (var message in messages)
            {
                MessageStack.AppendLine(message);
            }
        }

        private static StringBuilder _messages;

        /// <summary>
        /// Gets the messages generated by running migrations.
        /// </summary>
        /// <remarks>
        /// Will contain the messages from the last migration to run until reset is called, or another migration is started.
        /// </remarks>
        public static StringBuilder MessageStack
        {
            get { return _messages ?? (_messages = new StringBuilder()); }
            private set { _messages = value; }

        }
    }
}